#include "gd32f3x0.h"
#include "SPI_Ctrl.h"
#include "SPI_Flash.h"

void SPI_Config(void)
{
    SPI_InitPara  SPI_InitStructure;

    /* SPI1 configuration */
    SPI_InitStructure.SPI_TransType = SPI_TRANSTYPE_FULLDUPLEX;
    SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER;
    SPI_InitStructure.SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT;
    SPI_InitStructure.SPI_SCKPL = SPI_SCKPL_LOW;
    SPI_InitStructure.SPI_SCKPH = SPI_SCKPH_1EDGE;
    SPI_InitStructure.SPI_SWNSSEN = SPI_SWNSS_SOFT;
    SPI_InitStructure.SPI_PSC = SPI_PSC_32;
    SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;
    SPI_InitStructure.SPI_CRCPOL = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    /* SPI3 configuration ------------------------------------------------------*/
    SPI_InitStructure.SPI_TransType = SPI_TRANSTYPE_FULLDUPLEX;
    SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER;
    SPI_InitStructure.SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT;
    SPI_InitStructure.SPI_SCKPL = SPI_SCKPL_HIGH;
    SPI_InitStructure.SPI_SCKPH = SPI_SCKPH_2EDGE;
    SPI_InitStructure.SPI_SWNSSEN = SPI_SWNSS_SOFT;
    SPI_InitStructure.SPI_PSC = SPI_PSC_16;
    SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;
    SPI_InitStructure.SPI_CRCPOL = 7;
    SPI_Init(SPI3, &SPI_InitStructure);

    /* Disable/Enable SPI AND SPI3 CRC calculation */
    SPI_CRC_Enable(SPI1, DISABLE);
    SPI_CRC_Enable(SPI3, DISABLE);

    /* Enable SPI1 AND SPI3 */
    SPI_Enable(SPI1, ENABLE);
    SPI_Enable(SPI3, ENABLE);
}

void SPI_RXDMAConfig(SPI_TypeDef* SPIx, uint8_t* pBuffer, int size)
{
    DMA_InitPara  DMA_InitStructure;
    DMA_Channel_TypeDef* DMAy_Channelx;

    /* SPI DMA_Channel configuration */
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPIx->DTR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(pBuffer);
    DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALSRC;
    DMA_InitStructure.DMA_BufferSize = size;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
    DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
    DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;

    if(SPIx == SPI1)
    {
        DMAy_Channelx = DMA1_CHANNEL2;
    }
    else if(SPIx == SPI2)
    {
        DMAy_Channelx = DMA1_CHANNEL4;
    }
    else
    {
        DMAy_Channelx = DMA2_CHANNEL1;
    }
    DMA_DeInit(DMAy_Channelx);
    DMA_Init(DMAy_Channelx, &DMA_InitStructure);
}

void SPI_EnableDMARX(SPI_TypeDef* SPIx)
{
    DMA_Channel_TypeDef* DMAy_Channelx;
    if(SPIx == SPI1)
    {
        DMAy_Channelx = DMA1_CHANNEL2;
    }
    else if(SPIx == SPI2)
    {
        DMAy_Channelx = DMA1_CHANNEL4;
    }
    else
    {
        DMAy_Channelx = DMA2_CHANNEL1;
    }

    DMA_Enable(DMAy_Channelx, ENABLE);
}

void SPI_DisableDMARX(SPI_TypeDef* SPIx)
{
    uint32_t DMAy_FLAG;
    DMA_Channel_TypeDef* DMAy_Channelx;

    if(SPIx == SPI1)
    {
        DMAy_Channelx = DMA1_CHANNEL2;
        DMAy_FLAG = DMA1_FLAG_TC2;
    }
    else if(SPIx == SPI2)
    {
        DMAy_Channelx = DMA1_CHANNEL4;
        DMAy_FLAG = DMA1_FLAG_TC4;
    }
    else
    {
        DMAy_Channelx = DMA2_CHANNEL1;
        DMAy_FLAG = DMA2_FLAG_TC1;
    }

    DMA_ClearBitState(DMAy_FLAG);
    DMA_Enable(DMAy_Channelx, DISABLE);
}

void SPI_TXDMAConfig(SPI_TypeDef* SPIx, unsigned char* pBuffer, int size)
{
    DMA_InitPara  DMA_InitStructure;
    DMA_Channel_TypeDef* DMAy_Channelx;

    /* SPI3 DMA_Channel configuration */
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPIx->DTR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(pBuffer);
    DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALDST;
    DMA_InitStructure.DMA_BufferSize = size;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
    DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
    DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
    if(SPIx == SPI1)
    {
        DMAy_Channelx = DMA1_CHANNEL3;
    }
    else if(SPIx == SPI2)
    {
        DMAy_Channelx = DMA1_CHANNEL5;
    }
    else
    {
        DMAy_Channelx = DMA2_CHANNEL2;
    }

    DMA_DeInit(DMAy_Channelx);
    DMA_Init(DMAy_Channelx, &DMA_InitStructure);
}

void SPI_EnableDMATX(SPI_TypeDef* SPIx)
{
    DMA_Channel_TypeDef* DMAy_Channelx;
    if(SPIx == SPI1)
    {
        DMAy_Channelx = DMA1_CHANNEL3;
    }
    else if(SPIx == SPI2)
    {
        DMAy_Channelx = DMA1_CHANNEL5;
    }
    else
    {
        DMAy_Channelx = DMA2_CHANNEL2;
    }

    DMA_Enable(DMAy_Channelx, ENABLE);
}

void SPI_DisableDMATX(SPI_TypeDef* SPIx)
{
    uint32_t DMAy_FLAG;
    DMA_Channel_TypeDef* DMAy_Channelx;

    if(SPIx == SPI1)
    {
        DMAy_Channelx = DMA1_CHANNEL3;
        DMAy_FLAG = DMA1_FLAG_TC2;
    }
    else if(SPIx == SPI2)
    {
        DMAy_Channelx = DMA1_CHANNEL5;
        DMAy_FLAG = DMA1_FLAG_TC4;
    }
    else
    {
        DMAy_Channelx = DMA2_CHANNEL2;
        DMAy_FLAG = DMA2_FLAG_TC1;
    }

    DMA_ClearBitState(DMAy_FLAG);
    DMA_Enable(DMAy_Channelx, DISABLE);
}

int SPI_Tuner_BufferWrite(uint8_t* pBuffer, uint16_t NumByteToWrite)
{
    uint16_t txIdx = 0;

    while(txIdx < NumByteToWrite)
    {
        /* Loop while DR register in not emplty */
        while(SPI_I2S_GetBitState(SPI_TUNER_CH, SPI_FLAG_TBE) == RESET);

        /* Send byte through the SPI_TUNER_CH peripheral */
        SPI_I2S_SendData(SPI_TUNER_CH, pBuffer[txIdx]);

        txIdx++;
    }

    while(SPI_I2S_GetBitState(SPI_TUNER_CH, SPI_FLAG_TBE) == RESET);

    txIdx = 0;
    while(txIdx < 50)
    {
        txIdx++;
    }

    return txIdx;
}

int SPI_Tuner_BufferRead(uint8_t* pBuffer, uint16_t NumByteToRead)
{
    uint16_t rxIdx = 0;

    /*Clear the last read*/
    if(SPI_I2S_GetBitState(SPI_TUNER_CH, SPI_FLAG_TBE) == SET)
    {
        SPI_I2S_ReceiveData(SPI_TUNER_CH);
    }

    while(rxIdx < NumByteToRead)
    {
        /* Loop while DR register in not emplty */
        while(SPI_I2S_GetBitState(SPI_TUNER_CH, SPI_FLAG_TBE) == RESET);

        /* Send byte through the SPI_TUNER_CH peripheral */
        SPI_I2S_SendData(SPI_TUNER_CH, 0);

        /* Wait to receive a byte */
        while(SPI_I2S_GetBitState(SPI_TUNER_CH, SPI_FLAG_RBNE) == RESET);

        /* Return the byte read from the SPI bus */
        pBuffer[rxIdx] = SPI_I2S_ReceiveData(SPI_TUNER_CH);

        rxIdx++;
    }

    rxIdx = 0;
    while(rxIdx < 50)
    {
        rxIdx++;
    }

    return rxIdx;
}

